﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.SharePoint.Taxonomy;
using System.Text.RegularExpressions;
using System.Diagnostics;
using Microsoft.SharePoint;
using System.Globalization;
using System.Xml.Serialization;
using System.Xml.Linq;

namespace TaxManager
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonImportTerms_Click(object sender, EventArgs e)
        {
            try
            {
                if (LoadedTermGroup == null)
                    return;
                using (SPSite site = new SPSite(textBoxSiteCollectionURL.Text))
                {
                    AddTermsTo(textBoxGroupName.Text, textBoxSetName.Text, LoadedTermGroup.ChildTermSets[0].ChildTerms[0], site);
                }
                MessageBox.Show(string.Format("Done adding terms successfully. Added {0} term(s) out of {1} term(s).", TermsAddedCount, TermLoadedCount));
            }
            catch (Exception Ex)
            {
                MessageBox.Show(string.Format("Error importing terms.\nError Details:\n{0}\nStack Trace:\n{1}", Ex.Message, Ex.StackTrace));
            }
        }
        TermGroupInfo LoadedTermGroup;
        public void ReadTermsXml(string FilePath)
        {
            XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(TermGroupInfo));
            using (System.IO.StreamReader reader = new System.IO.StreamReader(FilePath))
            {
                LoadedTermGroup = (TermGroupInfo)serializer.Deserialize(reader);
            }
        }
        int TermsAddedCount = 0;
        int TermLoadedCount = 0;
        public void AddTermsTo(string groupName, string termSetName, TermInfo terms, SPSite site)
        {
            TermsAddedCount = 0;

            if (site == null)
            {
                MessageBox.Show("Error opening site collection");
                return;
            }
            TaxonomySession taxonomySession = new TaxonomySession(site);
            if (taxonomySession == null)
            {
                MessageBox.Show("Error connecting to the meta data service");
                return;
            }
            if (taxonomySession.TermStores.Count <= 0)
            {
                MessageBox.Show("No term stores found in the farm");
                return;
            }
            TermStore termStore = taxonomySession.TermStores[listBoxTermStores.SelectedIndex];
            if (taxonomySession == null)
            {
                MessageBox.Show("Error loading the default termstore");
                return;
            }
            //create new group if the groupName was not created.              
            Microsoft.SharePoint.Taxonomy.Group group = termStore.Groups.Where(g => g.Name == groupName).Count() > 0 ? termStore.Groups[groupName] : termStore.CreateGroup(groupName);
            //create new term set if the termSetName was not created.   
            TermSet termSet = group.TermSets.Where(s => s.Name == termSetName).Count() > 0 ? group.TermSets[termSetName] : group.CreateTermSet(termSetName);

            //add terms to term set.  

            //Check if the term exists
            Microsoft.SharePoint.Taxonomy.Term CurrentTerm = null;
            CurrentTerm = termSet.GetTerm(new Guid(terms.ID));
            if (CurrentTerm == null)
            {
                CurrentTerm = termSet.CreateTerm(terms.Name, int.Parse(terms.Lcid), new Guid(terms.ID));
                TermsAddedCount++;
            }

            //Add sub terms if any
            if (terms.ChildTerms != null)
            {
                foreach (TermInfo term in terms.ChildTerms)
                {
                    AddTermsTo(term, site, termStore, termSet, CurrentTerm);
                }
            }


            termStore.CommitAll();
        }
        public void AddTermsTo(TermInfo term, SPSite site, TermStore termStore, TermSet termSet, Microsoft.SharePoint.Taxonomy.Term ParentTerm)
        {
            //Check if the term exists
            //TermLoadedCount++;
            Microsoft.SharePoint.Taxonomy.Term CurrentTerm = null;
            CurrentTerm = termSet.GetTerm(new Guid(term.ID));
            if (CurrentTerm == null)
            {
                CurrentTerm = ParentTerm.CreateTerm(term.Name, int.Parse(term.Lcid), new Guid(term.ID));
                TermsAddedCount++;
            }

            //Add sub terms if any
            if (term.ChildTerms != null)
            {
                foreach (TermInfo subterm in term.ChildTerms)
                {
                    AddTermsTo(subterm, site, termStore, termSet, CurrentTerm);
                }
            }

        }

        private void buttonLoadTerms_Click(object sender, EventArgs e)
        {
            try
            {
                if (openFileDialogMain.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    ReadTermsXml(openFileDialogMain.FileName);
                }
                PopulateTermsToTree();
                MessageBox.Show(string.Format("Loaded {0} term(s) successfully", TermLoadedCount));
            }
            catch (Exception Ex)
            {
                MessageBox.Show(string.Format("Error Loading terms.\nError Details:\n{0}\nStack Trace:\n{1}", Ex.Message, Ex.StackTrace));
            }
        }
        private void PopulateTermsToTree()
        {
            TermLoadedCount = 0;
            if (LoadedTermGroup != null)
            {
                TermLoadedCount++;
                TreeNode Root = treeViewTerms.Nodes.Add(LoadedTermGroup.Name);
                if (LoadedTermGroup.ChildTermSets != null)
                {
                    foreach (TermSetInfo termset in LoadedTermGroup.ChildTermSets)
                    {
                       TreeNode TermSetRoot = Root.Nodes.Add(termset.Name);
                       if (termset.ChildTerms != null)
                        {
                            foreach (TermInfo subterm in termset.ChildTerms)
                            {
                                AddTermToTree(subterm, TermSetRoot);
                            }

                        }
                    }
                }
            }
        }

        private void AddTermToTree(TermInfo TermToAdd, TreeNode Root)
        {
            TermLoadedCount++;
            TreeNode NewTerm = Root.Nodes.Add(TermToAdd.Name);
            if (TermToAdd.ChildTerms != null)
            {
                foreach (TermInfo subterm in TermToAdd.ChildTerms)
                {
                    AddTermToTree(subterm, NewTerm);
                }

            }
            if (TermToAdd.Labels != null)
            {
                TreeNode Labels = NewTerm.Nodes.Add("Labels");
                foreach (TermLabelInfo label in TermToAdd.Labels)
                {
                    Labels.Nodes.Add(label.Name);
                }
            }
        }

        private void buttonLoadStores_Click(object sender, EventArgs e)
        {
            listBoxTermStores.Items.Clear();
            try
            {
                using (SPSite site = new SPSite(textBoxSiteCollectionURL.Text))
                {
                    if (site == null)
                    {
                        MessageBox.Show("Error opening site collection");
                        return;
                    }
                    TaxonomySession taxonomySession = new TaxonomySession(site);
                    if (taxonomySession == null)
                    {
                        MessageBox.Show("Error connecting to the meta data service");
                        return;
                    }
                    if (taxonomySession.TermStores.Count <= 0)
                    {
                        MessageBox.Show("No term stores found in the farm");
                        return;
                    }
                    foreach (TermStore termStore in taxonomySession.TermStores)
                    {
                        listBoxTermStores.Items.Add(termStore.Name);
                    }
                    listBoxTermStores.SelectedIndex = 0;
                }
            }

            catch (Exception Ex)
            {
                MessageBox.Show(string.Format("Error Loading term store list.\nError Details:\n{0}\nStack Trace:\n{1}", Ex.Message, Ex.StackTrace));
            }
        }
        [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
        [System.SerializableAttribute()]
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        [System.Xml.Serialization.XmlRootAttribute("Group", IsNullable = false)]
        public partial class TermGroupInfo
        {
            private TermSetInfo[] childTermSets;
            private string nameField;

            private string guidField;

            [System.Xml.Serialization.XmlElementAttribute("TermSet")]
            public TermSetInfo[] ChildTermSets
            {
                get
                {
                    return this.childTermSets;
                }
                set
                {
                    this.childTermSets = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Name")]
            public string Name
            {
                get
                {
                    return this.nameField;
                }
                set
                {
                    this.nameField = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Guid")]
            public string ID
            {
                get
                {
                    return this.guidField;
                }
                set
                {
                    this.guidField = value;
                }
            }
        }
        [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
        [System.SerializableAttribute()]
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        [System.Xml.Serialization.XmlRootAttribute("TermSet", IsNullable = false)]
        public partial class TermSetInfo
        {
            private TermInfo[] childTerms;
            private string nameField;

            private string guidField;

            [System.Xml.Serialization.XmlElementAttribute("Term")]
            public TermInfo[] ChildTerms
            {
                get
                {
                    return this.childTerms;
                }
                set
                {
                    this.childTerms = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Name")]
            public string Name
            {
                get
                {
                    return this.nameField;
                }
                set
                {
                    this.nameField = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Guid")]
            public string ID
            {
                get
                {
                    return this.guidField;
                }
                set
                {
                    this.guidField = value;
                }
            }
        }
        [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
        [System.SerializableAttribute()]
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        [System.Xml.Serialization.XmlRootAttribute("Term", IsNullable = false)]
        public partial class TermInfo
        {

            private TermInfo[] childTerms;

            private TermLabelInfo[] labels;
                
            private string nameField;

            private string guidField;

            private string lcidField;

            private string isDeprecatedField;

            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute("Label")]
            public TermLabelInfo[] Labels
            {
                get
                {
                    return this.labels;
                }
                set
                {
                    this.labels = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute("Term")]
            public TermInfo[] ChildTerms
            {
                get
                {
                    return this.childTerms;
                }
                set
                {
                    this.childTerms = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Name")]
            public string Name
            {
                get
                {
                    return this.nameField;
                }
                set
                {
                    this.nameField = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Guid")]
            public string ID
            {
                get
                {
                    return this.guidField;
                }
                set
                {
                    this.guidField = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Lcid")]
            public string Lcid
            {
                get
                {
                    return this.lcidField;
                }
                set
                {
                    this.lcidField = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("IsDeprecated")]
            public string IsDeprecated
            {
                get
                {
                    return this.isDeprecatedField;
                }
                set
                {
                    this.isDeprecatedField = value;
                }
            }
        }
        [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
        [System.SerializableAttribute()]
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        [System.Xml.Serialization.XmlRootAttribute("Label", IsNullable = false)]
        public partial class TermLabelInfo
        {

            private string nameField;

            private string lcidField;

            private string isDefault;


            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Name")]
            public string Name
            {
                get
                {
                    return this.nameField;
                }
                set
                {
                    this.nameField = value;
                }
            }
            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("Lcid")]
            public string Lcid
            {
                get
                {
                    return this.lcidField;
                }
                set
                {
                    this.lcidField = value;
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlAttributeAttribute("IsDefault")]
            public string IsDefault
            {
                get
                {
                    return this.isDefault;
                }
                set
                {
                    this.isDefault = value;
                }
            }
        }
        /// <remarks/>
        [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
        [System.SerializableAttribute()]
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
        public partial class NewDataSet
        {

            private TermInfo[] itemsField;

            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute("Term")]
            public TermInfo[] Items
            {
                get
                {
                    return this.itemsField;
                }
                set
                {
                    this.itemsField = value;
                }
            }
        }

        private void buttonExport_Click(object sender, EventArgs e)
        {
            if (saveFileDialogMain.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    ExportMetadataStore(textBoxSiteCollectionURL.Text, listBoxTermStores.SelectedItem.ToString(), textBoxGroupName.Text, saveFileDialogMain.FileName);
                }
                catch(Exception Ex)
                {
                    MessageBox.Show(string.Format("Error exporting terms.\nError Details:\n{0}\nStack Trace:\n{1}", Ex.Message, Ex.StackTrace));
                }
            }
        }
        public XElement GenerateNode(Microsoft.SharePoint.Taxonomy.Group g)
        {
            XElement rElement = new XElement("Group", new XAttribute("Name", g.Name), new
                                                                              XAttribute("Guid", g.Id),
                                                                              from termSet in g.TermSets
                                                                              select GenerateNode(termSet));
            return rElement;
        }
        public XElement GenerateNode(Microsoft.SharePoint.Taxonomy.TermSet termSet)
        {
             XElement rElement = new XElement("TermSet", new XAttribute("Name", termSet.Name), new
                                                                              XAttribute("Guid", termSet.Id),
                                                                              from term in termSet.Terms
                                                                              select GenerateNode(term));
            return rElement;
        }
        public XElement GenerateNode(Microsoft.SharePoint.Taxonomy.Term term)
        {
            int Language = 1033;
            foreach (Microsoft.SharePoint.Taxonomy.Label l in term.Labels)
            {
                if (l.IsDefaultForLanguage)
                {
                    Language = l.Language;
                    break;
                }
            }
            XElement rElement = new XElement("Term", new XAttribute("Name", term.Name), new
                                                                              XAttribute("Guid", term.Id),
                                                                              new XAttribute("Lcid", Language),
                                                                              new XAttribute("IsDeprecated", term.IsDeprecated?"true":"false"),
                                                                              from Subterm in term.Terms
                                                                              select GenerateNode(Subterm),
                                                                              from label in term.Labels
                                                                              select GenerateNode(label));
            return rElement;
        }
        public XElement GenerateNode(Microsoft.SharePoint.Taxonomy.Label label)
        {
            XElement rElement = new XElement("Label", new XAttribute("Name", label.Value),
                                                                              new XAttribute("Lcid", label.Language),
                                                                              new XAttribute("IsDefault", label.IsDefaultForLanguage ? "true" : "false"));
                                                                              
            return rElement;
        }
        private void ExportMetadataStore(string siteUrl, string managedMetaName, string groupName, string saveLocation)
        {

            using (SPSite site = new SPSite(siteUrl))
            {
                TaxonomySession session = new TaxonomySession(site);
                TermStore MetadataTermStore = session.TermStores[managedMetaName];
                foreach (Microsoft.SharePoint.Taxonomy.Group g in MetadataTermStore.Groups)
                {
                    if (g.Name.ToLower() == groupName.ToLower())
                    {
                        XElement metaStore = GenerateNode(g);
                        metaStore.Save(saveLocation);
                    }
                }
            }
        }
    }
}